/*
 * ContainerNodeObject.cpp
 *
 *  Created on: 03.10.2012
 *      Author: caffeine
 */

#include "ContainerNodeObject.h"

namespace irr{
namespace object{

ContainerNodeObject::ContainerNodeObject(irr::scene::ISceneManager*m,ContainerNodeObject*p) {
	manager=m;
	container_object=0;
	parent=0;
	setParent(p);
	container_mutex=irr::thread::createRecursiveMutex();
}

ContainerNodeObject::~ContainerNodeObject() {
	removeAllChild();
	destroyContainer();
	container_mutex->drop();
}

void ContainerNodeObject::removeAllChild(){
	for (irr::u32 i=0;i<childs.size();i++)
		childs[i]->drop();
	childs.clear();
}

irr::scene::ISceneNode*ContainerNodeObject::createAndGiveNode(){
	return manager->addEmptySceneNode(parent?parent->getContainer():0);
}

void ContainerNodeObject::createContainer(){
	if (isContainerCreated())
		return;
	container_mutex->lock();
	container_object=createAndGiveNode();
	container_object->grab();
	container_mutex->unlock();
}

void ContainerNodeObject::destroyContainer(){
	if (!isContainerCreated())
		return;
	container_mutex->lock();
	if (container_object->getParent())
		container_object->remove();
	container_object->drop();
	container_object=0;
	container_mutex->unlock();
}

irr::scene::ISceneNode*ContainerNodeObject::getContainer(){
	container_mutex->lock();
	irr::scene::ISceneNode*res=container_object;
	container_mutex->unlock();
	return res;
}

bool ContainerNodeObject::isContainerCreated(){
	return getContainer()!=0;
}

void ContainerNodeObject::setParent(ContainerNodeObject*p){
	if (parent==p)
		return;
	container_mutex->lock();

	if (parent)
		parent->removeChild(this);

	parent=p;
	if (parent)
		parent->addChild(this);
	if (isContainerCreated()){
		container_object->setParent(parent?parent->getContainer():manager->getRootSceneNode());
	}
	container_mutex->unlock();
}

ContainerNodeObject*ContainerNodeObject::getParent(){
	return parent;
}

void ContainerNodeObject::addChild(ContainerNodeObject*child){
	childs.push_back(child);
	child->grab();
}

ContainerNodeObject*ContainerNodeObject::getChild(irr::u32 index){
	return childs[index];
}

void ContainerNodeObject::removeChild(irr::u32 index){
	childs[index]->drop();
	childs.erase(index);
}

void ContainerNodeObject::removeChild(ContainerNodeObject*child){
	irr::s32 index=indexOf(child);
	if (index<0)
		return;
	removeChild(index);
}

irr::s32 ContainerNodeObject::indexOf(ContainerNodeObject*child){
	for (irr::u32 i=0;i<childs.size();i++)
		if (childs[i]==child)
			return i;
	return -1;
}

}//namespace object
}//namespace irr
